package com.sparrow.common.handler;

import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

/**
 * 通用的Handler 需要实现{@link Handler}接口 定义好Handler的类型和该类型下细分的key 就会自动注册Handler
 * 获取Handler的时候通过类型 和 key 去获取即可
 */
public class HandlerManager implements BeanPostProcessor {

    private static Logger logger = LoggerFactory.getLogger(HandlerManager.class);

    private final Map<Class<? extends Handler>, Map<Object, Handler>> handlerMap = new HashMap<>();

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Handler) {
            register(bean);
        }
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    private static HandlerManager instance;

    public HandlerManager() {
        instance = this;
    }

    public static HandlerManager getInstance() {
        return instance;
    }

    public void register(Object h) {
        Class<?> handlerClass = h.getClass();
        Class<?> inter = getType(handlerClass);
        if (inter == null) {
            return;
        }
        Handler p = (Handler) h;
        Map<Object, Handler> subMap = handlerMap.computeIfAbsent((Class<? extends Handler>) inter, k -> new HashMap<>());
        subMap.put(p.getHandlerKey(), p);
        logger.info("注册processor type:{} key:{}", inter.getSimpleName(), p.getHandlerKey());
    }

    @Nullable
    private Class<?> getType(Class<?> handlerClass) {
        Class<?> inter = null;
        // 获取实现的接口类型
        Type[] interfaces = handlerClass.getGenericInterfaces();
        for (Type type : interfaces) {
            // 判断是否为参数化类型
            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                if (Handler.class.isAssignableFrom((Class<?>) parameterizedType.getRawType())) {
                    // 获取泛型参数类型
                    Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                    if (actualTypeArguments.length > 0 && actualTypeArguments[0] instanceof Class<?>) {
                        inter = (Class<?>) actualTypeArguments[0];
                    }
                }
            }
        }
        if (inter == null) {//检查父类
            Class<?> superclass = handlerClass.getSuperclass();
            return superclass != null ? getType(superclass) : null;
        }
        return inter;
    }

    public <H extends Handler> H getHandler(Class<? extends Handler> clazz, Object key) {
        Map<Object, Handler> subMap = handlerMap.get(clazz);
        if (subMap == null) {
            return null;
        }
        return (H) subMap.get(key);
    }

    public <H extends Handler> Collection<H> getHandlers(Class<H> clazz) {
        Map<Object, Handler> subMap = handlerMap.get(clazz);
        if (subMap == null) {
            return Collections.emptySet();
        }
        return new HashSet<H>((Collection<? extends H>) subMap.values());
    }
}



